import { Slider } from 'antd';
import React from 'react';
import { Get, PostForm } from 'services';
import SparkMD5 from 'spark-md5'
type Status = 'waiting' | 'uploading' | 'success' | 'fail' | 'pause'
interface IFile {
    data: File,
    status: Status,
    progress: number
}
interface IChunk {
    start: number,
    end: number
}
export default () => {
    const [curFile, setCurFile] = React.useState<IFile>()
    let chunkList = React.useRef<IChunk[]>([]).current
    let md5 = React.useRef<string>('').current
    const onFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
        if (event.target.files?.length === 0) return
        const file = {
            data: event.target.files?.[0] as File,
            status: 'uploading' as Status,
            progress: 0
        }
        setCurFile(file)
        md5 = await md5File(file.data) as string
        checkMD5(file.data)
    }

    const md5File = (file: File) => {
        return new Promise((resolve, reject) => {
            const chunkSize = 1024 * 1024
            let current = 0
            const total = file.size / chunkSize
            const spark = new SparkMD5.ArrayBuffer()
            const fileReader = new FileReader()
            const list: IChunk[] = []
            fileReader.onload = function (e) {
                console.log('read chunk ', current + 1)
                spark.append(e.target?.result as ArrayBuffer)
                current++
                if (current < total) {
                    loadNext()
                } else {
                    chunkList = list
                    resolve(spark.end())
                }
            }
            function loadNext() {
                const start = current * chunkSize
                const end = Math.min(start + chunkSize, file.size)
                const blob = file.slice(start, end)
                list.push({ start, end })
                fileReader.readAsArrayBuffer(blob)
            }
            loadNext()
        })
    }

    const [src, setSrc] = React.useState('')
    const checkMD5 = async (file: File) => {
        Get('/upload/check/file', { md5, name: file.name })
            .then((res) => {
                console.log(res)
                if (res.filePath ) {
                    setSrc(res.filePath)
                    setCurFile({ data: file, status: 'success', progress: 100 })
                } else if (res.chunkList) {
                    startUpload(file, res.chunkList)
                }
            })
    }
    const startUpload = async (file: File, exists: string[]) => {
        console.log(chunkList)
        let uploaded = 0
        for (let i = 0; i < chunkList.length; i++) {
            if (exists.includes(i + '')) {
                uploaded++
                continue
            }
            await uploadChunk(file, chunkList[i], i)
            const progress = uploaded / chunkList.length
            setCurFile({ data: file, status: 'uploading', progress })
            uploaded++
        }
        const res = await Get('/upload/merge', { md5, name: file.name })
        setCurFile({ data: file, progress: 100, status: 'success' })
        setSrc(res.filePath)
    }

    const uploadChunk = async (file: File, chunk: IChunk, index: number) => {
        return new Promise((resolve, reject) => {
            const blob = file.slice(chunk.start, chunk.end)
            const data = {
                file: blob,
                total: chunkList.length,
                index,
                md5
            }
            console.log(data)
            PostForm('/upload', data).then(() => {
                resolve(index)
            }).catch((e) => {
                reject(e)
            })
        })
    }

    return (
        <div>
            <input className="mb20" type="file" onChange={onFileChange} disabled={curFile?.status === 'uploading'}></input>
            
            {
                curFile && 
                <div>
                    <Slider style={{width: 400}} value={curFile.progress * 100 } max={100} />
                </div>
            }
            <img src={src} alt=""/>
        </div>
    )
}